package beastick.utility;

//Copyright 2008 Tofig Kareemov, estereos@gmail.com
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

import java.util.Hashtable;

import beastick.configurator.SConfigurator;

public class CStringFilter extends CUtilityMethods
{
  private final int I_MODE_NONE    = 0;
  private final int I_MODE_INCLUDE = 1;
  private final int I_MODE_EXCLUDE = 2;
  private final int I_MODES        = 3;
  private String[]  sInclude       = new String[0];
  private String[]  sExclude       = new String[0];
  private Hashtable oIncludeCache  = new Hashtable();
  private Hashtable oExcludeCache  = new Hashtable();
  private int       iCacheMaxLimit = 100;

  class CResult
  {
    int     iIndex  = -1;
    boolean bPassed = false;
  }

  public CStringFilter()
  {
    super();
  }

  public CStringFilter(String sFilterParameterName)
  {
    super();
    LoadFilters(sFilterParameterName);
  }

  public synchronized void LoadFilters(String sFilterParameterName)
  {
    SConfigurator.SetMyInstanceFieldsExplicitly(this, sFilterParameterName);
    oIncludeCache.clear();
    oExcludeCache.clear();
    sInclude = new String[SConfigurator.GetInt(sFilterParameterName
      + ".sInclude")];
    for (int i = 0; i < sInclude.length; ++i)
    {
      sInclude[i] = SConfigurator.GetString(sFilterParameterName + ".sInclude."
        + i);
    }
    sExclude = new String[SConfigurator.GetInt(sFilterParameterName
      + ".sExclude")];
    for (int i = 0; i < sExclude.length; ++i)
    {
      sExclude[i] = SConfigurator.GetString(sFilterParameterName + ".sExclude."
        + i);
    }
  }

  private CResult InnerPassed(int iMode, String sCandidate)
  {
    CResult oResult = null;
    String[] sFilter = null;
    Hashtable oCache = null;
    if (iMode == I_MODE_INCLUDE)
    {
      sFilter = sInclude;
      oCache = oIncludeCache;
    }
    else if (iMode == I_MODE_EXCLUDE)
    {
      sFilter = sExclude;
      oCache = oExcludeCache;
    }
    else
    {
      return new CResult();
    }
    if (sFilter.length <= 0)
    {
      return new CResult();
    }
    if (iCacheMaxLimit > 0)
    {
      CResult oCachedResult = (CResult) oCache.get(sCandidate);
      if (oCachedResult != null)
      {
        return oCachedResult;
      }
    }
    oResult = new CResult();
    for (int i = 0; i < sFilter.length; ++i)
    {
      if (CMatcher.StaticMatchesPattern(sCandidate, sFilter[i]))
      {
        oResult.bPassed = true;
        oResult.iIndex = i;
        break;
      }
    }
    if (iCacheMaxLimit > 0)
    {
      if (oCache.size() >= iCacheMaxLimit)
      {
        oCache.clear();
      }
      oCache.put(sCandidate, oResult);
    }
    return oResult;
  }

  public boolean IncludePassed(String sCandidate)
  {
    return InnerPassed(I_MODE_INCLUDE, sCandidate).bPassed;
  }

  public boolean ExcludePassed(String sCandidate)
  {
    return InnerPassed(I_MODE_EXCLUDE, sCandidate).bPassed;
  }

  public synchronized int IncludePassedIndex(String sCandidate)
  {
    return InnerPassed(I_MODE_INCLUDE, sCandidate).iIndex;
  }

  public synchronized int ExcludePassedIndex(String sCandidate)
  {
    return InnerPassed(I_MODE_EXCLUDE, sCandidate).iIndex;
  }

  public String GetExcludeFilterRow(int iIndex)
  {
    String sResult = "";
    if (iIndex < sExclude.length)
    {
      sResult = sExclude[iIndex];
    }
    return sResult;
  }

  public String GetIncludeFilterRow(int iIndex)
  {
    String sResult = "";
    if (iIndex < sInclude.length)
    {
      sResult = sInclude[iIndex];
    }
    return sResult;
  }
  
  public boolean Passed(String sCandidate)
  {
    boolean bResult = InnerPassed(I_MODE_INCLUDE, sCandidate).bPassed;
    if (bResult)
    {
      bResult = !InnerPassed(I_MODE_EXCLUDE, sCandidate).bPassed;
    }
    return bResult;
  }

  public synchronized int GetCacheMaxLimit()
  {
    return iCacheMaxLimit;
  }

  public synchronized void SetCacheMaxLimit(int cacheMaxLimit)
  {
    iCacheMaxLimit = cacheMaxLimit;
  }
  
  public synchronized void SetFilters(String[] isIncludePattern, String[] isExcludePattern)
  {
    oIncludeCache.clear();
    oExcludeCache.clear();
    sInclude = isIncludePattern;
    sExclude = isExcludePattern;
  }

}